package xin.nick.minicat;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.*;

/**
 * @author Nick
 * @date 2021/6/20
 * @description
 */
public class RequestProcess {

    private MiniCatContent miniCatContent;

    private ServerSocket serverSocket;


    public RequestProcess() {
    }

    public RequestProcess(MiniCatContent miniCatContent) {
        this.miniCatContent = miniCatContent;
    }


    public void init() throws Exception {
        int port = miniCatContent.getPort();
        serverSocket = new ServerSocket(miniCatContent.getPort());
        System.out.println("MiniCat start on port: " + port);

        // 初始化线程池
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(miniCatContent.getMaxNumPoolSize());
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                miniCatContent.getCorePoolSize(),
                miniCatContent.getMaxNumPoolSize(),
                miniCatContent.getKeepAliveTime(),
                miniCatContent.getUnit(),
                workQueue,
                threadFactory,
                handler
        );

        while (true) {
            Socket socket = serverSocket.accept();
            RequestThread requestThread = new RequestThread(socket, miniCatContent);
            threadPoolExecutor.execute(requestThread);
        }
    }


    private class RequestThread extends Thread {
        private Socket socket;
        private MiniCatContent miniCatContent;

        public RequestThread() {}

        public RequestThread(Socket socket, MiniCatContent miniCatContent) {
            this.socket = socket;
            this.miniCatContent = miniCatContent;
        }

        @Override
        public void run() {
            InputStream inputStream = null;
            try {
                // 拿到 Request 和 Response
                inputStream = socket.getInputStream();
                Request request = new Request(inputStream);
                Response response = new Response(socket.getOutputStream());
                request.setMiniCatContent(miniCatContent);
                response.setMiniCatContent(miniCatContent);

                // 拿到 url 的数组,进行匹配操作
                List<String> urls = request.getUrls();
                MiniCatConfiguration miniCatConfiguration;
                if(Objects.nonNull(urls) && urls.size() > 1) {
                    List<String> projectList = miniCatContent.getProjectList();
                    String projectName = urls.get(0);
                    if(projectList.contains(projectName)) {
                        miniCatConfiguration = miniCatContent
                                .getProjectConfigurationMap().get(projectName);
                        handleRequest( miniCatConfiguration, request, response);
                        return;
                    }
                }

                // 过完所有的都没有,则设置为默认的configuration再进行处理
                String projectName = miniCatContent.getDefaultProjectName();
                miniCatConfiguration = miniCatContent
                        .getProjectConfigurationMap().get(projectName);
                handleRequest(miniCatConfiguration, request, response);
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }


        }

        private void handleRequest(MiniCatConfiguration miniCatConfiguration,
                                   Request request, Response response) throws Exception {
            String url = request.getUrl();
            // 根据项目名,进行截取真正的url,进行获取 Servlet进行处理请求
            String projectName = miniCatConfiguration.getProjectName();
            int subIndex = url.indexOf(projectName);
            String realUrl = url;
            if(-1 != subIndex) {
                realUrl = url.substring(subIndex + projectName.length());
            }

            // 交给静态文件
            if(Objects.isNull(url) || Objects.isNull(miniCatConfiguration)) {
                response.outputStatic(miniCatConfiguration.getProjectName() + File.separator +url);
            } else {

                Map<String, Servlet> nameServletMap = miniCatConfiguration.getServletObjectMap();
                // 如果没有的话,则进行新建map
                if (nameServletMap == null) {
                    nameServletMap = new HashMap<>();
                }
                Servlet servlet = nameServletMap.get(realUrl);
                // 还是为空的话,则进行获取className,进行新建Servlet
                if (Objects.isNull(servlet)) {
                    Map<String, String> nameServletClassMap = miniCatConfiguration.getServletClassNameMap();
                    // URL名字和Class名Map存在的话,接进行下一步,
                    if (Objects.nonNull(nameServletClassMap)) {
                        String className = nameServletClassMap.get(realUrl);
                        // className 存在的情况下,下一步,
                        // 创建 Servlet对象,并执行
                        if(Objects.nonNull(className)) {
                            servlet = (Servlet) Class.forName(className).newInstance();
                            servlet.init();
                            nameServletMap.put(realUrl, servlet);
                            servlet.service(request, response);
                            return;
                        }
                    }
                    // 交给静态资源处理
                    response.outputStatic(miniCatConfiguration.getProjectName() + File.separator + realUrl);
                } else {
                    servlet.service(request, response);
                }
            }
        }
    }
}
